﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Plat.WfProcess.Common;
using Plat.WfProcess.Business;
using Plat.WfProcess.DataModel;
using Plat.WfProcess.Utility;

namespace Plat.WfProcess.Engine
{
    /// <summary>
    /// 节点执行器的抽象类
    /// </summary>
    internal abstract class NodeMediator : IDisposable
    {
        #region 属性列表
        private ActivityExecutionContext activityExecutionContext;
        protected ActivityExecutionContext ActivityExecutionContext
        {
            get
            {
                return activityExecutionContext;
            }
        }

        /// <summary>
        /// 数据库上下文
        /// </summary>
        private ProcessModelDataContext _wfLinqDataContext;
        protected ProcessModelDataContext WfLinqDataContext
        {
            get
            {
                if (_wfLinqDataContext == null)
                {
                    _wfLinqDataContext = DataContextFactory.CreateWfLinqDataContext();
                    return _wfLinqDataContext;
                }
                else
                    return _wfLinqDataContext;
            }
        }

        protected Queue<WorkItem> _ToDoAutoWorkItemQueue;
        internal Queue<WorkItem> ToDoAutoWorkItemQueue
        {
            get
            {
                if (_ToDoAutoWorkItemQueue == null)
                    _ToDoAutoWorkItemQueue = new Queue<WorkItem>();
                
                return _ToDoAutoWorkItemQueue;
            }
        }

        #endregion

        #region 抽象方法列表

        internal abstract NodeBase CreateNewNode(ActivityEntity activity);
        internal abstract void ExecuteWorkItem();
        
        #endregion

        internal NodeMediator(ActivityExecutionContext actExecutionObject)
        {
            activityExecutionContext = actExecutionObject;
        }

        /// <summary>
        /// 遍历执行当前节点后面的节点
        /// </summary>
        /// <param name="previousActivityInstance"></param>
        /// <param name="currentNode"></param>
        internal virtual bool ContinueForwardCurrentNode(NodeBase fromNode,
            ActivityResource activityResource)
        {
            bool isContinuingSucceed = false;
            ActivityManager am = new ActivityManager(fromNode.Activity.ProcessGUID);
            NextActivityMatchedResult nextActivityMatchedResult = am.GetNextActivityList(fromNode.ActivityInstance.ProcessInstanceGUID,
                fromNode.Activity,
                activityResource.ConditionKeyValuePair,
                activityResource,
                (a, b) => a.NextActivityPerformers.ContainsKey(b.ActivityGUID));

            if (nextActivityMatchedResult.MatchedType == NextActivityMatchedType.Successed)
            {
                //根据是否有下一步的活动节点，给出WorkItemExecutedStatus值
                if (nextActivityMatchedResult.Root.HasChildren)
                {
                    ContinueForwardCurrentNodeRecurisivly(nextActivityMatchedResult.Root,
                        fromNode,
                        activityResource.ConditionKeyValuePair);
                    isContinuingSucceed = true;
                    WorkItemExecutedResult workItemExecutedResult = WorkItemExecutedResult.CreateWorkItemExecutedResult(WorkItemExecutedStatus.Successed);
                }
            }
            return isContinuingSucceed;
        }

        /// <summary>
        /// 递归执行节点
        /// </summary>
        /// <param name="root"></param>
        /// <param name="fromNode"></param>
        /// <param name="conditionKeyValuePair"></param>
        protected void ContinueForwardCurrentNodeRecurisivly(NextActivityComponent root,
            NodeBase fromNode,
            ConditionKeyValuePair conditionKeyValuePair)
        {
            foreach (NextActivityComponent c in root)
            {
                if (c.HasChildren)
                {
                    //此节点类型为分支或合并节点类型：首先需要实例化当前节点(自动完成)
                    NodeBase gatewayNode = GatewayNodeFactory.CreateNewNode(c.Activity);
                    ICompleteAutomaticlly autoGatewayNode = (ICompleteAutomaticlly)gatewayNode;
                    GatewayExecutedResult gatewayResult = autoGatewayNode.CompleteAutomaticlly(ActivityExecutionContext.ProcessInstance,
                        c.Transition,
                        fromNode.ActivityInstance,
                        ActivityExecutionContext.ActivityResource,
                        WfLinqDataContext);

                    if (gatewayResult.Status == GatewayExecutedStatus.Successed)
                    {
                        //遍历后续子节点
                        ContinueForwardCurrentNodeRecurisivly(c,
                            gatewayNode,
                            conditionKeyValuePair);
                    }
                    else
                    {
                        WorkItemExecutedResult workItemExecutedResult = WorkItemExecutedResult.CreateWorkItemExecutedResult(WorkItemExecutedStatus.FallBehindOfXOrJoin);
                    }
                }
                else if (c.Activity.IsWorkItemNode)
                {
                    //此节点类型为任务节点：根据fromActivityInstance的类型判断是否可以创建任务
                    if (fromNode.ActivityInstance.State == (short)NodeStateEnum.Completed)
                    {
                        //创建新任务节点
                        WorkItem workItem = (WorkItem)WorkItemNodeFactory.CreateNewNode(c.Activity);
                        workItem.CreateNewWorkItemWithTransitionInstance(ActivityExecutionContext.ProcessInstance,
                            c.Transition,
                            fromNode.ActivityInstance,
                            ActivityExecutionContext.ActivityResource,
                            WfLinqDataContext);

                        //新任务加入队列
                        if (workItem.IsAutomanticWorkItem)
                        {
                            ToDoAutoWorkItemQueue.Enqueue(workItem);
                        }
                    }
                    else
                    {
                        //下一步的任务节点没有创建，需给出提示信息
                        if ((fromNode.Activity.GatewayDirectionType | GatewayDirectionEnum.AllJoinType)
                            == GatewayDirectionEnum.AllJoinType)
                        {
                            WorkItemExecutedResult workItemExecutedResult = WorkItemExecutedResult.CreateWorkItemExecutedResult(WorkItemExecutedStatus.WaitingForOthersJoin);
                        }
                    }
                }
                else if (c.Activity.NodeType == NodeTypeEnum.EndNode)
                {
                    //此节点为完成结束节点，结束流程
                    NodeBase endNode = new EndNode(c.Activity);
                    ICompleteAutomaticlly autoEndNode = (ICompleteAutomaticlly)endNode;
                    autoEndNode.CompleteAutomaticlly(ActivityExecutionContext.ProcessInstance,
                        c.Transition,
                        fromNode.ActivityInstance,
                        ActivityExecutionContext.ActivityResource,
                        WfLinqDataContext);
                }
                else
                {
                    WorkItemExecutedResult workItemExecutedResult = WorkItemExecutedResult.CreateWorkItemExecutedResult(WorkItemExecutedStatus.Failed);
                    throw new XmlDefinitionException(string.Format("未知的节点类型：{0}", c.Activity.NodeType.ToString()));
                }
            }
        }

        #region IDisposable 成员

        public void Dispose()
        {
            if (WfLinqDataContext != null)
            {
                WfLinqDataContext.Dispose();
            }
        }

        #endregion
    }
}
